#include "qtlistwidget.h"

#include <QPainter>
#include <QScrollBar>
#include <QMouseEvent>
#include <QDebug>

QtListWidget::QtListWidget(QWidget *parent) : QAbstractScrollArea(parent)
{
    this->setMouseTracking(true);
    this->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);

    initAttributes();
    connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjust()));
}

QtListWidget::~QtListWidget()
{
    clear();
}

void QtListWidget::clear()
{
    foreach(QtListWidgetItem *_item, m_items) {
        delete _item;
        _item = Q_NULLPTR;
    }

    m_items.clear();
}

QtListWidgetItem *QtListWidget::currentItem()
{
    return itemAt(m_currentItem);
}

QtListWidgetItem *QtListWidget::itemAt(int index)
{
    if (m_items.contains(index))
        return m_items.value(index);
    return Q_NULLPTR;
}

void QtListWidget::addItem(QtListWidgetItem *_item)
{
    int index = m_items.size();
    _item->setId(index);
    m_items.insert(index, _item);
    adjust();
    viewport()->update();
}

bool QtListWidget::isContains(const QString &txt)
{
    foreach(QtListWidgetItem *_item, m_items) {
        if (!QString::compare(txt, _item->subText())){
            return true;
        }
    }

    return false;
}

void QtListWidget::adjust()
{
    int _rowsShown = ((viewport()->height() - 4) / m_itemHeight);
    int lineCount = m_items.size() - 1;

    verticalScrollBar()->setRange(0, lineCount - _rowsShown);
    verticalScrollBar()->setPageStep(_rowsShown);

    int value = verticalScrollBar()->value();
    int offset = verticalScrollBar()->isVisible() ? 0 : verticalScrollBar()->width();
    m_firstItem = value;
    int nYoffset = 0;
    foreach(QtListWidgetItem *_item, m_items) {
        if (_item->id() >= m_firstItem && nYoffset < this->height()) {
            _item->setRect(QRect(0, nYoffset, viewport()->width() + offset, m_itemHeight));
            nYoffset += m_itemHeight;
        } else {
            _item->setRect(QRect(0, 0, 0, 0));
        }
    }
}

void QtListWidget::initAttributes()
{
    m_firstItem = 0;
    m_itemHeight = 60;

    m_iconSize = QSize(40, 40);

    m_marginLeft = 10;
    m_marginRight = 10;
    m_marginTop = 0;
    m_marginBottom = 0;
    m_currentItem = 0;
    m_hoverItem = -1;

    m_backgroundColor = QColor("#dedede");
    m_itemBorder = Qt::transparent;
    m_itemColor = Qt::transparent;
    m_itemSelectedColor = QColor("#33000000");
    m_itemHoverColor = QColor("#22000000");
    m_textColor = QColor("#000000");
    m_subTextColor = QColor("#999999");

#if 0
    for (int i = 0; i < 100; i++) {
        m_items.insert(i, new QtListWidgetItem(i, QString("item %1").arg(i + 1), "subtext"));
    }
#endif
}

QColor QtListWidget::itemColor() const
{
    return m_itemColor;
}

void QtListWidget::setItemColor(const QColor &itemColor)
{
    m_itemColor = itemColor;
}

QColor QtListWidget::itemHoverColor() const
{
    return m_itemHoverColor;
}

void QtListWidget::setItemHoverColor(const QColor &itemHoverColor)
{
    m_itemHoverColor = itemHoverColor;
}

QColor QtListWidget::itemSelectedColor() const
{
    return m_itemSelectedColor;
}

void QtListWidget::setItemSelectedColor(const QColor &itemSelectedColor)
{
    m_itemSelectedColor = itemSelectedColor;
}

void QtListWidget::setIconSize(const QSize &iconSize)
{
    m_iconSize = iconSize;
}

QColor QtListWidget::subTextColor() const
{
    return m_subTextColor;
}

void QtListWidget::setSubTextColor(const QColor &subTextColor)
{
    m_subTextColor = subTextColor;
}

QColor QtListWidget::textColor() const
{
    return m_textColor;
}

void QtListWidget::setTextColor(const QColor &textColor)
{
    m_textColor = textColor;
}

int QtListWidget::itemHeight() const
{
    return m_itemHeight;
}

void QtListWidget::setItemHeight(int itemHeight)
{
    m_itemHeight = itemHeight;
}

QColor QtListWidget::itemBorder() const
{
    return m_itemBorder;
}

void QtListWidget::setItemBorder(const QColor &itemBorder)
{
    m_itemBorder = itemBorder;
}

QColor QtListWidget::backgroundColor() const
{
    return m_backgroundColor;
}

void QtListWidget::setBackgroundColor(const QColor &backgroundColor)
{
    m_backgroundColor = backgroundColor;
}

void QtListWidget::resizeEvent(QResizeEvent *)
{
    adjust();
}

void QtListWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(viewport());
    painter.setRenderHints(QPainter::Antialiasing);
    painter.fillRect(viewport()->rect(), m_backgroundColor);
    foreach(QtListWidgetItem *_item, m_items) {
        if (_item->id() >= m_firstItem) {
            drawItemInfo(&painter, _item);
        }
    }
}

void QtListWidget::drawItemInfo(QPainter *painter, QtListWidgetItem *_item)
{
    painter->save();
    painter->setPen(m_itemBorder);
    QColor colrBrush = _item->id() == m_hoverItem ? m_itemHoverColor : m_itemColor;
    painter->setBrush(_item->id() == m_currentItem ? m_itemSelectedColor : colrBrush);
    painter->drawRect(_item->rect());

    QPixmap pixmap = _item->icon();
    QRect rectIcon = QRect(_item->rect().left(), _item->rect().top(), 0, _item->rect().height());
    int yOffset = (rectIcon.height() - m_iconSize.height()) / 2;
    QFont font = painter->font();
    if (!pixmap.isNull() && rectIcon.height() > 0)
    {
        rectIcon = QRect(rectIcon.left() + m_marginLeft, rectIcon.top() + yOffset, m_iconSize.width(), m_iconSize.height());
        painter->drawPixmap(rectIcon, pixmap);
    }

    int nTxtW = _item->rect().width() - m_marginLeft - m_marginRight - rectIcon.width() - 10;
    int nTxtH = (_item->rect().height() - m_marginTop - m_marginBottom) / 2;
    QRect rectText(rectIcon.right() + 10, _item->rect().top(), nTxtW, nTxtH);
    painter->setPen(m_textColor);
    font.setPixelSize(14);
    painter->setFont(font);
    painter->drawText(rectText, Qt::AlignBottom, _item->text());

    rectText = QRect(rectText.left(), rectText.bottom(), rectText.width(), rectText.height());
    painter->setPen(m_subTextColor);
    font.setPixelSize(12);
    painter->setFont(font);
    painter->drawText(rectText, Qt::AlignTop, _item->subText());

    painter->restore();
}

void QtListWidget::mousePressEvent(QMouseEvent *e)
{
    foreach(QtListWidgetItem *_item, m_items) {
        if (_item->rect().contains(e->pos())) {
            if (m_currentItem != _item->id()) {
                viewport()->update(m_items.value(m_currentItem)->rect());
                m_currentItem = _item->id();
                viewport()->update(_item->rect());
                emit itemClicked(m_currentItem);
            }
            break;
        }
    }
}

void QtListWidget::mouseMoveEvent(QMouseEvent *e)
{
    foreach(QtListWidgetItem *_item, m_items) {
        if (_item->rect().contains(e->pos())) {
            if (m_hoverItem != _item->id()) {
                if (m_items.contains(m_hoverItem)) {
                    viewport()->update(m_items.value(m_hoverItem)->rect());
                }
                m_hoverItem = _item->id();
                viewport()->update(_item->rect());
            }
            break;
        }
    }
}

void QtListWidget::leaveEvent(QEvent *e)
{
    if (m_items.contains(m_hoverItem)) {
        QRect rect = m_items.value(m_hoverItem)->rect();
        m_hoverItem = -1;
        viewport()->update(rect);
    }

    QAbstractScrollArea::leaveEvent(e);
}

///////////////////////////////////////////////////////////////////////
QtListWidgetItem::QtListWidgetItem(int _id) : m_id(_id),m_rect(0, 0, 0, 0),
    m_text(""),m_subText("")
{

}

QtListWidgetItem::QtListWidgetItem(int _id, const QString &_txt) :
    m_id(_id),m_rect(0, 0, 0, 0),
    m_text(_txt),m_subText("")
{

}

QtListWidgetItem::QtListWidgetItem(int _id, const QString &_txt, const QString &_subTxt) :
    m_id(_id),m_rect(0, 0, 0, 0),
    m_text(_txt),m_subText(_subTxt)
{

}

QtListWidgetItem::QtListWidgetItem(int _id, const QString &_txt,
                                   const QString &_subTxt,
                                   const QPixmap &icon) :
    m_id(_id),m_rect(0, 0, 0, 0),
    m_text(_txt),m_subText(_subTxt),m_icon(icon)
{

}

QtListWidgetItem::~QtListWidgetItem()
{

}

int QtListWidgetItem::id()
{
    return m_id;
}

void QtListWidgetItem::setId(const int &_id)
{
    m_id = _id;
}

QRect QtListWidgetItem::rect() const
{
    return m_rect;
}

void QtListWidgetItem::setRect(const QRect &rect)
{
    m_rect = rect;
}

QPixmap QtListWidgetItem::icon() const
{
    return m_icon;
}

void QtListWidgetItem::setIcon(const QPixmap &icon)
{
    m_icon = icon;
}

QString QtListWidgetItem::text() const
{
    return m_text;
}

void QtListWidgetItem::setText(const QString &text)
{
    m_text = text;
}

QString QtListWidgetItem::subText() const
{
    return m_subText;
}

void QtListWidgetItem::setSubText(const QString &subText)
{
    m_subText = subText;
}
